package com.zhss.demo.zk;

import com.zhss.demo.ConsolHelp;
import com.zhss.demo.ThreadHelp;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;

import java.util.concurrent.TimeUnit;

public class ZkLockDemo {
    public static void main(String[] args) throws Exception {
        m2();
        //lockone();
    }

    /**
     * 读写锁
     * 1, 在创建读写锁时, 它里面有两个锁, 一个读锁, 一个写锁;
     * 2, 这两个锁的不同点, 为lock_name及这个目录下允许建立几个路径;
     * 3, read锁, 可以有Integer.MAX个线程可以获取锁;
     * 4, 而write锁, 这个最上层的目录下, 只能有一个写锁, 且, 当有读锁的时候是不行的;
     * 5, 从这里可以看出来, 它的这个功能, 是依赖于, 目录下可以建立几个路径的;
     *
     * @throws Exception 异常
     */
    private static void m2() throws Exception {
        InterProcessReadWriteLock readWriteLock = ZkLockHelp.getReadWriteLock("cjm_readWriteLock");
        InterProcessMutex readLock = readWriteLock.readLock();
        readLock.acquire();
        InterProcessMutex writeLock = readWriteLock.writeLock();
        writeLock.acquire();


        while (true) {
            String msg = ConsolHelp.get();
            if ("close".equals(msg)) {
                break;
            } else {
                System.err.println(msg);
            }
        }
        ZkLockHelp.shutdown();
    }

    /**
     * 可重入锁的示例
     * <p>
     * 它的可重入, 是依赖于一个map的private final ConcurrentMap<Thread, LockData> threadData = Maps.newConcurrentMap();
     * <p>
     * 当这个map中, 有一个线程中的LockData的数据的话, 那证明, 这个线程已经获取到了锁, 那么它只要递增好了;
     * <p>
     * 它的那个目录下, 还是只有一个路径的;
     *
     * @throws Exception 异常
     */
    private static void lockone() throws Exception {
        InterProcessMutex lock = ZkLockHelp.getReentrnLock("re_entr_temp");
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    ThreadHelp.print("try to get lock");
                    lock.acquire();
                    ThreadHelp.print("get lock ready");
                    ThreadHelp.sleep(10000, TimeUnit.MINUTES);
                    lock.release();
                } catch (Exception e) {
                }
            }
        };

        Thread thread1 = new Thread(runnable, "thread-1");
        Thread thread2 = new Thread(runnable, "thread-2");
        Thread thread3 = new Thread(runnable, "thread-3");
        Thread thread4 = new Thread(runnable, "thread-4");

        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();

        monitor(thread1, thread2, thread3, thread4);
    }

    public static void monitor(
            Thread thread1,
            Thread thread2,
            Thread thread3,
            Thread thread4
    ) {
        while (true) {
            String msg = ConsolHelp.get();
            if ("1".equals(msg)) {
                thread1.interrupt();
                ThreadHelp.print("thread 1 release lock .");
            }
            if ("2".equals(msg)) {
                thread2.interrupt();
                ThreadHelp.print("thread 2 release lock .");
            }
            if ("3".equals(msg)) {
                thread3.interrupt();
                ThreadHelp.print("thread 3 release lock .");
            }
            if ("4".equals(msg)) {
                thread4.interrupt();
                ThreadHelp.print("thread 4 release lock .");
            }
            if ("close".equals(msg)) {
                ThreadHelp.print("shutdown now .");
                thread1.interrupt();
                thread2.interrupt();
                thread3.interrupt();
                thread4.interrupt();
                break;
            }
            System.err.println(msg);
        }
        ZkLockHelp.shutdown();
    }
}
